#include "ds1302.h"

uint8_t ds1302_to_bcd(uint8_t value)
{
  return ((value / 10) << 4 | (value % 10));
}

uint8_t ds1302_from_bcd(uint8_t bcd)
{
  return ((bcd & 0xF0) >> 4) * 10 + (bcd & 0x0F);
}

void ds1302_write(uint8_t data)
{
  uint8_t i;
  for(i=0; i<8; i++)
  {
    DS1302_SCK = 0;
    DS1302_SDA = data & 0x01;
    data >>= 1;
    DS1302_SCK = 1;
  }
}

uint8_t ds1302_read_register(uint8_t addr)
{
  EA = 0;
  uint8_t data=0;
  DS1302_RST = 0;
  __nop();
  DS1302_SCK = 0;
  __nop();
  DS1302_RST = 1;
  __nop();
  ds1302_write(addr | 0x01);
  for (int i=0; i<8; ++i) {
    DS1302_SCK = 0;
    data >>= 1;
    if (DS1302_SDA) {
      data |= 0x80;
    }
    DS1302_SCK = 1;
  }
  DS1302_RST = 0;
  __nop();
  DS1302_RST = 0;
  DS1302_SCK = 0;
  __nop();
  DS1302_SCK = 1;
  __nop();
  DS1302_SDA = 0;
  __nop();
  DS1302_SDA = 1;
  __nop();
  EA = 1;
  return data;
}

void ds1302_write_register(uint8_t addr, uint8_t data)
{
  EA = 0;
  DS1302_RST = 0;
  __nop();
  DS1302_SCK = 0;
  __nop();
  DS1302_RST = 1;
  __nop();
  ds1302_write(addr);
  ds1302_write(data);
  DS1302_SCK = 0;
  DS1302_RST = 0;
  EA = 1;
}

void ds1302_halt()
{
  ds1302_write_enable();
  ds1302_write_register(DS1302_ADDR_SEC, ds1302_read_register(DS1302_ADDR_SEC) | 0x80);
  ds1302_write_disable();
}

void ds1302_start()
{
  ds1302_write_enable();
  ds1302_write_register(DS1302_ADDR_SEC, ds1302_read_register(DS1302_ADDR_SEC) & 0x7F);
  ds1302_write_disable();
}
